/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.funda.xmppserver.handlers;

import com.funda.xmppserver.ComponentParser;
import com.funda.xmppserver.XMPPClient;
import com.funda.xmppserver.mysql.DBManager;
import com.funda.xmppserver.writer.XMPPPacketWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 *
 * @author kurinchi
 */
public class AuthHandler implements ComponentParser {

    XMPPPacketWriter packetwriter;
    XMPPClient client;
    Connection conn;
    Statement smt;
    ResultSet rs;
    Boolean valid = true;
    Map<Object, Object> attribs = new HashMap<Object, Object>();
    ArrayList<Object> ns = new ArrayList<Object>();

    public AuthHandler(XMPPPacketWriter packetwriter,XMPPClient client) {
        this.packetwriter = packetwriter;
        this.client=client;

        conn = DBManager.getConn();

        attribs.put("mechanism", "PLAIN");

        ns.add("urn:ietf:params:xml:ns:xmpp-sasl");
    }

    public void parseElement(XMLStreamReader xmlReader) throws XMLStreamException {

        System.out.println("Auth!!");

        //checks attributes
        for (int i = 0; i < xmlReader.getAttributeCount(); i++) {
            //System.out.println(xmlReader.getAttributeLocalName(i) + " -> " + xmlReader.getAttributeValue(i));
            String attribname = xmlReader.getAttributeLocalName(i);
            String attribval = xmlReader.getAttributeValue(i);
            if (!(attribs.containsKey(attribname) && (attribval.equalsIgnoreCase(attribs.get(attribname).toString())))) {
                valid = false;
            }

        }

        //checks namespace
        for (int i = 0; i < xmlReader.getNamespaceCount(); i++) {
            //System.out.println(xmlReader.getNamespaceURI(i));
            String nsname = xmlReader.getNamespaceURI(i);
            if (!ns.contains(nsname)) {
                valid = false;
            }
        }
        System.out.println("Auth Result : " + valid);

        String plainstr = xmlReader.getElementText();
        System.out.println("PLAIN : " + plainstr);
        if (valid && isAuthenticated(plainstr)) {
            packetwriter.sendSuccess();
        } else {
            packetwriter.sendFailure();
        }
        //packetwriter.sendStreamResponse();
    }

    public Boolean isAuthenticated(String plainstr) {
        try {
            BASE64Decoder decode = new BASE64Decoder();
            String decodedstr = new String(decode.decodeBuffer(plainstr));
            String username = decodedstr.substring(1, decodedstr.lastIndexOf((char) 0));

            client.setUsername(username);
            //System.out.println(decodedstr+" : "+decodedstr.substring(1,decodedstr.lastIndexOf((char)0)));


            smt = conn.createStatement();
            rs = smt.executeQuery("select * from userdetails where userid='" + username + "'");

            while (rs.next()) {
                //System.out.println(rs.getString("id")+" : "+rs.getString("userid")+" : "+rs.getString("password"));
                BASE64Encoder encoder = new BASE64Encoder();
                String enstr = ((char) 0) + rs.getString("userid") + ((char) 0) + rs.getString("password");
                //System.out.println(enstr);
                if (encoder.encode(enstr.getBytes()).equals(plainstr)) {
                    System.out.println("Authenticated!!");
                    client.setAuthenticated(true);
                    return true;
                }
                System.out.println("Authentication Failed!!");
            }

        } catch (SQLException ex) {
            Logger.getLogger(AuthHandler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(AuthHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;
    }
}
